﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
using GRV11;

namespace gpuimp.core
{
    [Serializable]
    public class EdgeDetect : Modifier
    {
        public EdgeDetect()
        {
            fragPass1 = null;
            fragPass2 = null;
            vertProg = null;

            id = -1;
            Name = "Edge Detect";
            shaderPass1 = shaderPass2 = -1;

            setFragProg("");
            setVertProg("");

            twoPass = true;

            setupShader();
        }

        public void setCopyShader()
        {
            GRSupport.SupportShaderProgramSelect(CanvasManager.gr, Tool.copyShader);

            int shaderDiffuse = (int)CanvasManager.gr.glGetUniformLocationARB(Tool.copyShader, "diffuseMap");
            CanvasManager.gr.glUniform1iARB(shaderDiffuse, 0);
        }

        public void setupToolViewport(GR gr)
        {
            // Viewport 
            Point imageSize = CanvasManager.CurrentCanvas.ImageSize;
            // Viewport to same size as the texture
            gr.glViewport(0, 0, imageSize.X, imageSize.Y);

            // Clear the viewport
            gr.glClearColor(0.5f, 0.5f, 0.5f, 1.0f);
            gr.glClear(GR.GL_COLOR_BUFFER_BIT | GR.GL_DEPTH_BUFFER_BIT);

            // PROJECTION matrix
            gr.glMatrixMode(GR.GL_PROJECTION);
            gr.glLoadIdentity();
            double aspectRatio = 1.0;
            if (0 != imageSize.Y)
                aspectRatio = ((double)(imageSize.X) / (double)(imageSize.Y));

            int halfWidth = imageSize.X;// / 2;
            int halfHeight = imageSize.Y;// / 2;
            gr.gluOrtho2D(-halfWidth, halfWidth, -halfHeight, halfHeight);

            // MODELVIEW matrix, typically used to transform individual models
            gr.glMatrixMode(GR.GL_MODELVIEW);
            gr.glLoadIdentity();
        }

        public override void ActivatePass1()
        {
            GRSupport.SupportShaderProgramSelect(CanvasManager.gr, this.shaderPass1);

            int shaderDiffuse = (int)CanvasManager.gr.glGetUniformLocationARB(this.shaderPass1, "Texture0");
            int shaderImagesize = (int)CanvasManager.gr.glGetUniformLocationARB(this.shaderPass1, "imageSize");
            int shaderEdgeSize = (int)CanvasManager.gr.glGetUniformLocationARB(this.shaderPass1, "edgeSize");
            CanvasManager.gr.glUniform1iARB(shaderDiffuse, 0);
            CanvasManager.gr.glUniform1fARB(shaderEdgeSize, 1.0f);
            Point p = CanvasManager.CurrentCanvas.ImageSize;
            CanvasManager.gr.glUniform2fARB(shaderImagesize, p.X, p.Y);
        }

        public override void ActivatePass2()
        {
        }

        public override void Deactivate()
        {
            GRSupport.SupportShaderProgramSelect(CanvasManager.gr, 0);
        }

        public override void setFragProg(String frag)
        {
            fragPass1 = @"
uniform sampler2D Texture0;
uniform vec2 imageSize;
uniform float edgeSize;

varying vec2 texCoord;

float Greyscale(vec4 color)
{
   return 0.3 * color.r + 0.59 * color.g + 0.11 * color.b;
}

void main(void)
{
   float dU = edgeSize / imageSize.x;
   float dV = edgeSize / imageSize.y;
   
   vec4 color = texture2D(Texture0, texCoord);
   vec4 s0 = Greyscale(color);
   float s1 = Greyscale( texture2D(Texture0, vec2(texCoord.x - dU, texCoord.y) ) );
   float s2 = Greyscale( texture2D(Texture0, vec2(texCoord.x, texCoord.y - dV) ) );
   float s3 = Greyscale( texture2D(Texture0, vec2(texCoord.x + dU, texCoord.y) ) );
   float s4 = Greyscale( texture2D(Texture0, vec2(texCoord.x, texCoord.y + dV) ) );
      
   float edges = abs(s1 - s3) + abs(s2 - s4);
   
   gl_FragColor = vec4(edges, edges, edges, color.a);
}
";

            fragPass2 = @"";
        }


        public override void setVertProg(String vert)
        {
            //this.vertProg = vertProg;
            vertProg = @"
varying vec2  texCoord;
void main(void)
{
   gl_Position = ftransform();
   texCoord = gl_MultiTexCoord0.xy;
}
";
        }
    }
}
